package server;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import server.container.Context;
import server.container.Engine;
import server.container.Host;
import server.container.Wrapper;
import server.mapper.Mapper;
import sun.tools.jar.resources.jar;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

public class Catalina implements Lifecycle{

    public static Server server;

    public static void initServer(){

        InputStream resourceAsStream = Mapper.class.getClassLoader().getResourceAsStream("server.xml");
        SAXReader saxReader = new SAXReader();
        Server server = new Server();
        try {
            Document document = saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> serviceNodes = rootElement.selectNodes("//Service");
            List<Service> serviceList = new ArrayList<>();
            server.setServiceList(serviceList);
            serviceNodes.forEach(serviceNode -> {
                Service service = new Service();
                serviceList.add(service);
                List<Element> engineNodes = serviceNode.selectNodes("//Engine");
                Element engineNode = engineNodes.get(0);
                Engine engine = new Engine();
                service.setEngine(engine);
                List<Element> hostNodes = engineNode.selectNodes("//Host");
                List<Host> hostList = new ArrayList<>();
                engine.setHostList(hostList);
                hostNodes.forEach(hostNode -> {
                    String name = hostNode.attribute("name").getStringValue();
                    String appBase = hostNode.attribute("appBase").getStringValue();
                    Host host = new Host();
                    host.setName(name);
                    host.setAppBase(appBase);
                    hostList.add(host);
                    // appBase下的目录注册成 Context
                    List<Context> contextList = initContext(appBase);
                    host.setContextList(contextList);
                });

                List<Element> connectorNodes = serviceNode.selectNodes("//Connector");
                List<Connector> connectorList = new ArrayList<>();
                service.setConnectorList(connectorList);
                connectorNodes.forEach(connectorNode -> {
                    String port = connectorNode.attribute("port").getStringValue();
                    Connector connector = new Connector();
                    connector.setPort(port);
                    connector.setService(service);
                    connectorList.add(connector);
                });
            });
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        Catalina.server = server;
    }

    private static List<Context> initContext(String appBase) {
        List<Context> contextList = new ArrayList<>();
        File dir = new File(appBase);
        if (dir.isDirectory()){
            for (File dirFile : dir.listFiles()) {
                Context context = new Context();
                ClassLoader loader = null;
                try {
                    URL url = new File(dirFile.getAbsolutePath()).toURI().toURL();
                    loader = URLClassLoader.newInstance(
                            new URL[] { url },
                            Catalina.class.getClassLoader()
                    );
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
                context.setDocBase(appBase+"/"+dirFile.getName());
                context.setPath("/"+dirFile.getName());
                context.setWrapperList(initServlet(context.getDocBase(),loader));
                contextList.add(context);
            }
        }
        return contextList;
    }

    private static List<Wrapper> initServlet(String docBase, ClassLoader loader) {

        SAXReader saxReader = new SAXReader();
        List<Wrapper> wrapperList = new ArrayList<>();
        try {
            Document document = saxReader.read(new File(docBase+"/web.xml"));
            List<Element>  webapps = document.selectNodes("//web-app");
            Element webapp = webapps.get(0);
//            Element rootElement = document.getRootElement();
            List<Element> selectNodes = webapp.selectNodes("//servlet");
            for (int i = 0; i < selectNodes.size(); i++) {
                Element element =  selectNodes.get(i);
                Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
                String servletName = servletnameElement.getStringValue();
                Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
                String servletClass = servletclassElement.getStringValue();
                Element servletMapping = (Element) webapp.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                Wrapper wrapper = new Wrapper();
                wrapper.setUrl(urlPattern);
                wrapper.setServlet((HttpServlet) Class.forName(servletClass, true, loader).newInstance());
                wrapperList.add(wrapper);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return wrapperList;
    }

    @Override
    public void start() {
        server.start();
    }
}
